package hanxx.menu.service.impl;

import hanxx.common.utils.StringUtils;
import hanxx.menu.dao.MenuDao;
import hanxx.menu.domain.SysMenu;
import hanxx.menu.service.MenuService;
import hanxx.security.dao.SysRoleDao;
import hanxx.security.domain.SysRole;
import hanxx.security.domain.SysUser;
import hanxx.system.service.impl.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * edit:韩鑫鑫
 * 部门:产品研发三部
 **/
@Service
public class MenuServiceImpl extends BaseServiceImpl<SysMenu, MenuDao> implements MenuService {
    @Autowired
    private MenuDao menuDao;
    @Autowired
    private SysRoleDao roleDao;

    @Override
    public List<SysMenu> getDataList() {
        return createChildren(menuDao.findAll(), menuDao.findMenusByParentId(0l));
    }

    private List<SysMenu> createChildren(List<SysMenu> allMenus, List<SysMenu> rootMenus){
        for(int i = 0;i < rootMenus.size();i++){
            List<SysMenu> rootChildrens = new ArrayList<>();
            for(int j = 0;j < allMenus.size();j++){
                if (allMenus.get(j).getParentId().equals(rootMenus.get(i).getMenuId())){
                    rootChildrens.add(allMenus.get(j));
                }
            }
            rootMenus.get(i).setChildren(createChildren(allMenus,rootChildrens));
        }
        return rootMenus;
    }

    /**
     * 根据角色ID查询菜单树信息
     *
     * @param roleId 角色ID
     * @return 选中菜单列表
     */
    @Override
    public List<Long> selectMenuListByRoleId(Long roleId) {
        SysRole role = roleDao.selectRoleById(roleId);
        StringBuilder sql = new StringBuilder(" select m.menu_id as menu_id from sys_menu m ");
        sql.append(" left join sys_role_menu rm on m.menu_id = rm.menu_id ");
        sql.append(" where rm.role_id =:roleId ");
        if (role.isMenuCheckStrictly()) {
            sql.append(" and m.menu_id not in (select m.parent_id from sys_menu m inner join sys_role_menu rm on m.menu_id = rm.menu_id and rm.role_id = :roleId)");
        }
        sql.append("  order by m.parent_id, m.order_num ");
        Map<String, Object> param = new HashMap<>();
        param.put("roleId", roleId);
        List<Map> r = menuDao.listMapBySqlLowercaseKey(sql.toString(), param);
        return r.stream().map(map -> Long.valueOf(map.get("menu_id").toString())).collect(Collectors.toList());
    }

    /**
     * 根据用户ID查询权限
     *
     * @param userId 用户ID
     * @return 权限列表
     */
    @Override
    public Set<String> selectMenuPermsByUserId(Long userId) {


        StringBuilder sql = new StringBuilder(" select distinct t.perms ");

        Map<String, Object> param = new HashMap<>();

        buildSql(sql, param, new SysMenu(), userId, false);

        List<Map> r = menuDao.listMapBySqlLowercaseKey(sql.toString(), param);

        Set<String> permsSet = r.stream().map(perm -> perm.get("perms")).filter(perm -> perm != null).map(perm -> Arrays.asList(perm.toString().trim().split(","))).flatMap(i -> i.stream()).collect(Collectors.toSet());

        return permsSet;
    }

    private void buildSql(StringBuilder sql, Map<String, Object> param, SysMenu menu, Long userId, boolean hasOrder) {

        StringBuilder from = new StringBuilder(" from sys_menu t ");
        StringBuilder where = new StringBuilder(" where 1=1 ");

        // 管理员显示所有菜单信息
        if (SysUser.isAdmin(userId)) {
            userId = null;
        }
        // 不是管理员关联角色菜单表
        if (userId != null) {
            from.append(" left join sys_role_menu rm on t.menu_id=rm.menu_id ");
            from.append(" left join sys_user_role ur on ur.role_id=rm.role_id ");

            param.put("user_id", userId);
            where.append(" and ur.user_id=:user_id ");
        }

        /*if (StringUtils.isNotEmpty(menu.getMenuName())) {
            where.append(" and t.menu_name like :menu_name ");
            param.put("menuName", "%" + menu.getMenuName() + "%");
        }*/

        if (StringUtils.isNotEmpty(menu.getVisible())) {
            where.append(" and t.visible=:visible ");
            param.put("visible", menu.getVisible());
        }

        if (StringUtils.isNotEmpty(menu.getStatus())) {
            where.append(" and t.status=:status ");
            param.put("status", menu.getStatus());
        }
        if (hasOrder) {
            where.append(" order by parent_id, order_num ");
        }

        sql.append(from).append(where);
    }
}
